﻿#define _CRT_SECURE_NO_WARNINGS 1

//之前实现构造函数时，初始化成员变量主要使用构造函数在函数体内赋值
//还可以使用初始化列表方式赋值

//初始化列表：以⼀个冒号开始，接着是⼀个以逗号分隔的数据成员列表，每个"成员变量"后⾯跟⼀个放在括号中的初始值或表达式



//语法理解上初始化列表可以认为是每个成员变量定义初始化的地⽅
//引⽤成员变量，const成员变量，没有默认构造的类类型变量，必须放在初始化列表位置进⾏初始化，否则会编译报错

#include <iostream>
using namespace std;

typedef int STDataType;
class Stack
{
public:
	Stack(int n)
	{
		cout << "Stack(int n = 4)" << endl;

		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}

	// st2(st1)
	Stack(const Stack& st)
	{
		// 需要对_a指向资源创建同样大的资源再拷贝值
		_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败!!!");
			return;
		}
		memcpy(_a, st._a, sizeof(STDataType) * st._top);
		_top = st._top;
		_capacity = st._capacity;
	}

	// st1 = st3
	// st1 = st1;
	Stack& operator=(const Stack& st)
	{
		if (this != &st)
		{
			free(_a);
			_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);
			if (nullptr == _a)
			{
				perror("malloc申请空间失败!!!");
				return *this;
			}
			memcpy(_a, st._a, sizeof(STDataType) * st._top);
			_top = st._top;
			_capacity = st._capacity;
		}

		return *this;
	}

	void Push(STDataType x)
	{
		if (_top == _capacity)
		{
			int newcapacity = _capacity * 2;
			STDataType* tmp = (STDataType*)realloc(_a, newcapacity *
				sizeof(STDataType));
			if (tmp == NULL)
			{
				perror("realloc fail");
				return;
			}
			_a = tmp;
			_capacity = newcapacity;
		}
		_a[_top++] = x;
	}

	void Pop()
	{
		_a[_top - 1] = -1;
		--_top;
	}

	int Top()
	{
		return _a[_top - 1];
	}

	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		//_a = nullptr;
		//_top = _capacity = 0;
	}
private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};


//class MyQueue
//{
//public:
//	MyQueue(int n, int& rx)
//		:_pushst(n)   
//		,_popst(n)
//		,_ref(rx)  //引用，const修饰的成员变量，没有默认构造的类类型变量 均需要在初始化列表中初始化
//		,_i(1)
//		, _a((int*)malloc(40))
//	{
//		_size = 1;   
//		//函数体内可以进行更复杂的处理 比如在初始化列表中动态开辟一个数组
//		for (size_t i = 0; i < 10; i++)
//			{
//				_a[i] = i;
//			}
//	}
//
//private:
//	// 成员变量声明
//	Stack _pushst;
//	Stack _popst;
//
//	int& _ref;
//	const int _i;
//
//	int _size;
//
//	int* _a = (int*)malloc(40);
//};
//
//
//int main()
//{
//	//之前初始化MyQueue时会调用其自定义类型成员变量的构造函数 但是若想给MyQueue初始化1000个空间无法实现 
//	/*MyQueue mq1;*/    //因为MyQueue并没有初始化赋值的地方，只有其成员变量栈有
//
//	//加上初始化了列表后就可以实现
//	int x = 0;
//	MyQueue mq1(1000, x);
//
//	return 0;
//}

class MyQueue
{
public:
	//尽量使⽤初始化列表初始化，因为那些你不在初始化列表初始化的成员也会⾛初始化列表
	MyQueue()
		//列表初始化时，优先使用列表中传的值，若没有，看成员变量声明的地方，调用声明处给的缺省值 按照声明顺序进行列表初始化
		:_pushst(2000)
		,_size(1)
		//, _a((int*)malloc(40))
	{
		// 尽量使用初始化列表，还需要进一步检查或处理
		// 再继续使用函数体处理
		if (_a == nullptr)
		{
			//...
		}
		else
		{
			for (size_t i = 0; i < 10; i++)
			{
				_a[i] = i;
			}
		}
	}
private:
	// 成员变量声明   声明顺序与列表初始化顺序一致，跟在初始化列表中出现的先后无关
	// C++11 声明给缺省值
	Stack _pushst = 1000;
	Stack _popst = 1000;

	int _size = 0;
	const int _i = 1;

	int* _a = (int*)malloc(40);
};


//总结:  成员列表走初始化列表的逻辑

//1、先看是否显式在初始化列表中，若有，则按初始化列表中的值来初始化
//2、若未显式在初始化列表  先看类中声明位置有无缺省值，若有则按缺省值初始化 若没有对于内置类型，看编译器处理，对于自定义类型，调用默认构造函数
//3、引用成员变量/const修饰的成员变量/没有默认构造函数的成员变量必须在初始化列表初始化.

